package handler

import (
	"bufio"
	"fmt"
	"io"
	"iptv_server/v3/src/settings"
	"net/http"
	"net/url"
	"strings"
)

func proxy_selector(w http.ResponseWriter, resp *http.Response) bool {
	bufr := bufio.NewReader(resp.Body)
	// 根据 前100个byte ;判断.
	bs, _ := bufr.Peek(100)
	s := string(bs)
	ss := strings.Split(s, "\n")
	for _, s := range ss {
		s := strings.Trim(s, "\r\n ")
		if len(s) > 0 {
			if s == "#EXTM3U" {
				// m3u, m3u8
				return processM3U_proxy(w, resp, bufr)
			} else {
				buffered, _ := bufr.Peek(bufr.Buffered())
				w.Write(buffered)
				return false
			}
		}
	}
	buffered, _ := bufr.Peek(bufr.Buffered())
	w.Write(buffered)
	return false
}

func processM3U_proxy(w http.ResponseWriter, resp *http.Response, bufr *bufio.Reader) bool {
	// bufr := bufio.NewReader(resp.Body)
	// // 根据 前100个byte ;判断.
	// bs, _ := bufr.Peek(100)
	// s := string(bs)
	// ss := strings.Split(s, "\n")
	// for _, s := range ss {
	// 	s := strings.Trim(s, "\r\n ")
	// 	if len(s) > 0 {
	// 		if s == "#EXTM3U" {
	// 			break
	// 		} else {
	// 			buffered, _ := bufr.Peek(bufr.Buffered())
	// 			w.Write(buffered)
	// 			return false
	// 		}
	// 	}
	// }

	u := resp.Request.URL

	var line string
	var err error
	for {
		// 需要 分别处理 读/写 的error, 然后 退出!
		if err != nil {
			break
		}

		line, err = bufr.ReadString('\n')
		if err != nil {
			if err != io.EOF {
				fmt.Println("Error reading line:", err)
			}
			break
		}

		line1 := strings.TrimLeft(line, " ")
		line1 = strings.TrimRight(line1, "\r\n ")
		if len(line1) == 0 {
			_, err = io.WriteString(w, "\n")
			continue
		} else if strings.HasPrefix(line1, "#") {
			io.WriteString(w, line1)
			_, err = io.WriteString(w, "\n")
			continue
		}
		_, err = io.WriteString(w, settings.SiteDomain)
		io.WriteString(w, proxyPath)
		io.WriteString(w, "?url=")

		pre := strings.ToLower(line1[:8])
		if strings.HasPrefix(pre, "rtsp://") {
			io.WriteString(w, line1)
		} else if strings.HasPrefix(pre, "http://") || strings.HasPrefix(pre, "https://") {
			io.WriteString(w, url.QueryEscape(line1))
		} else {
			u2, _ := url.Parse(line1)
			fullurl := u.ResolveReference(u2)
			io.WriteString(w, url.QueryEscape(fullurl.String()))
		}
		io.WriteString(w, "\n")
		continue
	}
	return true
}

// // func newProxyHandler() {

// // }

// // package handler

// import (
// 	"crypto/tls"
// 	"fmt"
// 	"io"
// 	"iptv_server/v3/v2_src/handler/middleware"
// 	"iptv_server/v3/v2_src/handler/proxyhelper"
// 	"iptv_server/v3/v2_src/utils"
// 	"iptv_server/v3/v2_src/utils/common"
// 	parserdecoder "iptv_server/v3/v2_src/utils/parser_decoder"

// 	"net/http"
// 	"net/url"
// 	"strings"
// 	"time"
// )

// var (
// 	fallbackProxy            *proxyhelper.Fallback_redirect2fileServer
// 	defaultDecoderBuilderKey = "txt"
// )

// func initProxy(middles ...middleware.MiddleWare) {
// 	h := middleware.ApplyMiddles(&proxy{
// 		tr: &http.Transport{
// 			TLSClientConfig: &tls.Config{
// 				InsecureSkipVerify: true,
// 			},
// 		},
// 	}, middles...)

// 	fallbackProxy = proxyhelper.New_fallback_redirect2fileServer()

// 	// parsers = make(map[string]parser.ParserBuilder)
// 	// parsers["m3u"] = parser.NewM3U
// 	// parsers["m3u"]=&

// 	mux.Handle("/api/proxy", h)
// 	mux.Handle("/api/proxy/", h)

// }

// // var parsers map[string]parser.ParserBuilder

// type proxy struct {
// 	tr *http.Transport
// }

// // "/api/proxy/"
// // "0:/1:api/2:proxy/3:"
// func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {

// 	// if strings.HasPrefix(r.URL.Path, "/gc/") {
// 	// 	u = "https://gcalic.v.myalicdn.com" + r.URL.Path
// 	// } else {
// 	_ = r.ParseForm()
// 	u := r.Form.Get("url")
// 	if len(u) <= 0 {
// 		return
// 	}
// 	parseKey := r.Form.Get("parser")
// 	decodeKey := r.Form.Get("decoder")
// 	sorterKey := r.Form.Get("sorter")
// 	filterKey := r.Form.Get("filter")
// 	fmt.Printf("r.Form.Has(\"decoder\"): %v\n", r.Form.Has("decoder"))
// 	// }

// 	fmt.Printf("parseKey: %v\n", parseKey)
// 	fmt.Printf("decodeKey: %v\n", decodeKey)
// 	fmt.Printf("sorterKey: %v\n", sorterKey)
// 	fmt.Printf("filterKey: %v\n", filterKey)

// 	utils.Logger.Infof("%s method=proxy.GET, url=%s", r.RemoteAddr, u)
// 	if len(parseKey) > 0 {
// 		// use Cache, 不能所有都 cache ,比如 stream !
// 		// // 只有 parse 过的才使用cache
// 		if v, ok := stringCache.Get(r.URL.String()); ok {
// 			utils.Logger.Infof("cache hit : %s, len=%d method=proxy.GET, url=%s", r.RemoteAddr, len(v), r.URL.String())
// 			io.WriteString(w, v)
// 			return
// 		}
// 	}

// 	// resp, err := http.Get(u)
// 	client := &http.Client{
// 		Transport: p.tr,
// 		Timeout:   time.Second * 10,
// 	}
// 	resp, err := client.Get(u)
// 	if err != nil {
// 		utils.Logger.Debugf("proxy err:%v", err)
// 		parsedUrl, err := url.Parse(u)
// 		if err != nil {
// 			return
// 		}

// 		fallbackProxy.Redirect(parsedUrl, client, fallbackPort, w)
// 		return
// 	}

// 	utils.Logger.Debugf("proxy resp.StatusCode=%v,URL=%v,query=%v", resp.StatusCode, resp.Request.URL, resp.Request.URL.RawQuery)

// 	////已经 确认了, 自动重定向!
// 	// 但是重定向 之后  resp code==200而不是30x
// 	// 末尾 有获取 301的方法

// 	// u2 := resp.Request.URL.String()

// 	// for i := range 3 { // 最多 重定向3次, 需要手动处理 重定向吗?!还是会自动处理掉
// 	// 	utils.Logger.Infof("%d proxy StatusCode=%v", i, resp.StatusCode)
// 	// 	if resp.StatusCode == http.StatusMovedPermanently || resp.StatusCode == http.StatusFound {
// 	// 		u = resp.Header.Get("Location")
// 	// 		resp, err = client.Get(u)
// 	// 		if err != nil {
// 	// 			utils.Logger.Debugf("proxy err:%v", err)
// 	// 			w.WriteHeader(http.StatusNotFound)
// 	// 			return
// 	// 		}
// 	// 	} else {
// 	// 		break
// 	// 	}
// 	// }

// 	defer resp.Body.Close()

// 	if len(parseKey) > 0 {
// 		if parserBuilder, ok := parserdecoder.ParserBuilders.Get(parseKey); ok {
// 			var sorter common.Sorter
// 			var filter common.Filter
// 			if len(sorterKey) > 0 || len(filterKey) > 0 {
// 				client2 := &http.Client{
// 					Transport: &http.Transport{
// 						TLSClientConfig: &tls.Config{
// 							InsecureSkipVerify: true,
// 						},
// 					},
// 					Timeout: time.Second * 10,
// 				}

// 				sorter, filter = proxyhelper.Get_sorted_filter_mapper(client2, u, fallbackPort, fallbackBasePath, len(sorterKey) > 0, len(filterKey) > 0)
// 			}

// 			parser := parserBuilder(sorter, filter)
// 			if parsed, err := parser.Parse(resp.Body); err == nil {
// 				decoderBuilder, ok := parserdecoder.DecoderBuilders.Get(decodeKey)
// 				if !ok {
// 					decoderBuilder, ok = parserdecoder.DecoderBuilders.Get(defaultDecoderBuilderKey)
// 					if !ok {
// 						return
// 					}
// 				}

// 				decoder := decoderBuilder()
// 				strBuffer := &strings.Builder{}
// 				decoder.Decode(strBuffer, parsed)
// 				s := strBuffer.String()
// 				if r.Method == http.MethodGet {
// 					// 只有 parse 过的才使用cache
// 					stringCache.Save(r.URL.String(), s)
// 					utils.Logger.Infof("cache save : %s, len=%d method=proxy.GET, url=%s", r.RemoteAddr, len(s), r.URL.String())
// 				}
// 				// 先 save, 再 write.
// 				io.WriteString(w, s)
// 				// io.Copy(w, reader)
// 				return
// 			}
// 		}
// 		return
// 	}

// 	w.Header().Add(utils.HeaderKeyContentType, resp.Header.Get(utils.HeaderKeyContentType))
// 	io.Copy(w, resp.Body)
// }

// /*

// // 1
// 	baseHost := "https://www.example.com/"
// 	client := &http.Client{
// 		CheckRedirect: func(req *http.Request, via []*http.Request) error {
// 		return http.ErrUseLastResponse
// 		},
// 	}

// 	res, err := client.Get(baseHost)
// 	if err != nil {
// 		return
// 	}

// 	if res.StatusCode != 301 {
// 		return baseHost
// 	}

// 	return res.Header.Get("Location")

// */

// /*
// // 2
// type LogRedirects struct {
//     Transport http.RoundTripper
// }

// func (l LogRedirects) RoundTrip(req *http.Request) (resp *http.Response, err error) {
//     t := l.Transport
//     if t == nil {
//         t = http.DefaultTransport
//     }
//     resp, err = t.RoundTrip(req)
//     if err != nil {
//         return
//     }
//     switch resp.StatusCode {
//     case http.StatusMovedPermanently, http.StatusFound, http.StatusSeeOther, http.StatusTemporaryRedirect:
//         log.Println("Request for", req.URL, "redirected with status", resp.StatusCode)
//     }
//     return
// }

// */

// // encodeURIComponent(x)

// // https://blog.csdn.net/a772304419/article/details/134355619
// //// curl http://localhost:9966/api/proxy/?url=https%3A%2F%2Fblog.csdn.net%2Fa772304419%2Farticle%2Fdetails%2F134355619
// // https://server.lan
// // https%3A%2F%2Fserver.lan
// //// curl http://localhost:9966/api/proxy/?url=https%3A%2F%2Fserver.lan
// // http://server.lan:9966/
// // http%3A%2F%2Fserver.lan%3A9966%2F
// // curl http://localhost:9966/api/proxy/?url=http%3A%2F%2Fserver.lan%3A9966%2F

// // https://gcalic.v.myalicdn.com/gc/wgw05_1/index.m3u8?contentid=2820180516001

// // curl -I http://localhost:9966/api/proxy/?url=http%3A%2F%2Flocalhost%3A9966%2Fapi%2Fcode%2F302%3Fa%3Db

// // curl -I "http://localhost:9966/api/proxy/?parser=m3u&url=http%3A%2F%2Flocalhost%3A9966%2Fapi%2Fcode%2F302%3Fa%3Db"
// // curl http://localhost:9966/api/proxy/?parser=m3u&url=http://server22.lan:35455/tv.m3u
// // http://server.lan:9966/api/proxy/?parser=m3u&url=http://server22.lan:35455/tv.m3u
// // curl "http://server.lan:9966/api/proxy/?url=http://server22.lan:9966/box1_more_and_more/ok.live.txt"

// // http://server.lan:9966/api/proxy/?parser=m3u&url=http://server22.lan:35455/tv.m3u
